struct Sudoku{
    data: Vec<Vec<u32>>,
}


impl Sudoku{
    fn is_valid(&self) -> bool {
        // YOUR SOLUTION
        let row_len = self.data.len();
        let mut data_iter = self.data.iter();
        while let Some(col) = data_iter.next() {
            println!("col: {:?}", col);
            if col.len() != row_len {
                return false;
            }
            if !Self::only_contain_n(col.to_vec()) {
                return false;
            }
        }
        if !Self::little_squares_valitor(&self.data) {
            return false;
        }
        
        if !Self::column_valitor(&self.data) {
            return false;
        }
        true
    }


    fn little_squares_valitor(v: &Vec<Vec<u32>>) -> bool {
        let little_size = (v.len() as f64).sqrt();
        println!("little_size: {}", little_size);
        if little_size.floor() != little_size {
            return false;
        }
        let little_size = little_size as usize;
        for i in 0..little_size {
            for j in 0..little_size {
                let mut little_square = Vec::default();
                for i2 in 0..little_size {
                    for j2 in 0..little_size {
                        little_square.push(v[i * little_size + i2][j *little_size +  j2]);
                    }
                }
                if !Self::only_contain_n(little_square) {
                    return false;
                }
            }
        }
        true
    }
    
    fn column_valitor(v: &Vec<Vec<u32>>) -> bool {
        for i in 0..v.len() {
            let mut little_square = Vec::default();
            for j in 0..v.len() {
                little_square.push(v[j][i]);
            }
            if !Self::only_contain_n(little_square) {
                return false;
            }
        }
        true
    }

    fn only_contain_n(mut d: Vec<u32>) -> bool {
        let n = d.len();
        d.sort();
        let s = d.iter().map(|x| format!("{}", x) ).collect::<String>();
        let s1 = (1..=n).into_iter().map(|x| format!("{}", x)).collect::<String>();
        s == s1
    }
}


#[test]
fn good_sudoku() {
    let good_sudoku_1 = Sudoku{
        data: vec![
                vec![7,8,4, 1,5,9, 3,2,6],
                vec![5,3,9, 6,7,2, 8,4,1],
                vec![6,1,2, 4,3,8, 7,5,9],

                vec![9,2,8, 7,1,5, 4,6,3],
                vec![3,5,7, 8,4,6, 1,9,2],
                vec![4,6,1, 9,2,3, 5,8,7],
                
                vec![8,7,6, 3,9,4, 2,1,5],
                vec![2,4,3, 5,6,1, 9,7,8],
                vec![1,9,5, 2,8,7, 6,3,4]
            ]
    };
    
    let good_sudoku_2 = Sudoku{
        data: vec![
                vec![1, 4,  2, 3],
                vec![3, 2,  4, 1],
        
                vec![4, 1,  3, 2],
                vec![2, 3,  1, 4],
            ]
    };
    assert!(good_sudoku_1.is_valid());
    assert!(good_sudoku_2.is_valid());
}

#[test]
fn bad_sudoku() {
    let bad_sudoku_1 = Sudoku{
        data: vec![
                vec![1,2,3, 4,5,6, 7,8,9],
                vec![1,2,3, 4,5,6, 7,8,9],
                vec![1,2,3, 4,5,6, 7,8,9],

                vec![1,2,3, 4,5,6, 7,8,9],
                vec![1,2,3, 4,5,6, 7,8,9],
                vec![1,2,3, 4,5,6, 7,8,9],
                
                vec![1,2,3, 4,5,6, 7,8,9],
                vec![1,2,3, 4,5,6, 7,8,9],
                vec![1,2,3, 4,5,6, 7,8,9],
            ]
    };
    
    let bad_sudoku_2 = Sudoku{
        data: vec![
                vec![1,2,3,4,5],
                vec![1,2,3,4],
                vec![1,2,3,4],
                vec![1],
            ]
    };
    assert!(!bad_sudoku_1.is_valid());
    assert!(!bad_sudoku_2.is_valid());
}